﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Networking;
using Windows.Networking.Connectivity;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;
using Windows.System.Threading;

namespace App2
{
    public class ControlServer
    {
        private string accessCode;
        private DatagramSocket udpSendSocket, udpReceiveSocket, clientSocket;
        private int currentStatus;
        private const int waitForConnection = 0;
        private const int connected = 1;

        private const int BroadcastData = 0;
        private const int RequestFile = 1;
        private const int FileSummary = 2;
        private const int FilePart = 3;
        private const int EndFile = 4;
        private ThreadPoolTimer timer;
        private string hostDisplayName;
        public ControlServer()
        {
            currentStatus = waitForConnection;
            udpReceiveSocket = new DatagramSocket();
            udpReceiveSocket.MessageReceived += udpSocket_MessageReceived;
            udpReceiveSocket.BindServiceNameAsync("4455");

            udpSendSocket = new DatagramSocket();

            IReadOnlyList<HostName> names = NetworkInformation.GetHostNames();
            foreach (HostName name in names)
            {
                if (name.DisplayName == "127.0.0.1")
                    continue;
                hostDisplayName = name.DisplayName;
            }
            hostDisplayName = "192.168.2.108";
        }

        async void udpSocket_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
        {
            DataReader reader = args.GetDataReader();
            int dataType = reader.ReadInt32();

            if (dataType == RequestFile)
            {
                long dataSize1 = reader.ReadInt64();
                byte[] data1 = new byte[dataSize1];
                reader.ReadBytes(data1);

                long position = reader.ReadInt64();

                string accesscode = System.Text.Encoding.UTF8.GetString(data1, 0, data1.Length);

                if (clientSocket != null)
                {
                    if (clientSocket.Information.RemoteAddress.DisplayName != args.RemoteAddress.DisplayName)
                    {
                        clientSocket.Dispose();
                        clientSocket = null;
                        clientSocket = new DatagramSocket();
                        await clientSocket.ConnectAsync(args.RemoteAddress, "4455");
                    }
                }
                else
                {
                    clientSocket = new DatagramSocket();
                    await clientSocket.ConnectAsync(args.RemoteAddress, "4455");
                }
                SendFilePart(position);
            }
        }

        async void BroadcastService(ThreadPoolTimer timer)
        {
            DataWriter writer = new DataWriter(udpSendSocket.OutputStream);
            byte[] accessCodedata = System.Text.Encoding.UTF8.GetBytes(accessCode);
            byte[] ipData = System.Text.Encoding.UTF8.GetBytes(hostDisplayName);
            int datatype = 0;
            long datasize1 = ipData.Length;
            long datasize2 = accessCodedata.Length;
            writer.WriteInt32(datatype);
            writer.WriteInt64(datasize1);
            writer.WriteBytes(ipData);
            writer.WriteInt64(datasize2);
            writer.WriteBytes(accessCodedata);
            await writer.StoreAsync();
        }

        async void SendFilePart(long position)
        {
            DataWriter writer = new DataWriter(clientSocket.OutputStream);
            if (position < 1024)
            {
                int datatype = FilePart;
                long datasize1 = 1024;
                writer.WriteInt32(datatype);
                writer.WriteInt64(datasize1);
                byte[] bytes = new byte[1024];
                writer.WriteBytes(bytes);
            }
            else
            {
                int datatype = EndFile;
                writer.WriteInt32(datatype);
            }
            await writer.StoreAsync();
        }

        /// <summary>
        /// start service and create an accesscode
        /// </summary>
        /// <returns></returns>
        public String StartService()
        {
            Random random = new Random();
            double code = random.NextDouble() * 8000 + 1000;
            accessCode = ((int)code).ToString();
            if (timer == null)
            {
                udpSendSocket.ConnectAsync(new HostName("255.255.255.255"), "4455");
                timer = ThreadPoolTimer.CreatePeriodicTimer(new TimerElapsedHandler(BroadcastService), TimeSpan.FromSeconds(1));
            }
            return accessCode;
        }



    }
}
